refactor(examples): drop the inert root title from six catalog dashboards - #7634
Merged
Conversation
…boards The six `filtered-*` entries under `examples/schema-catalog/src/schemas/plugin-dashboard/` author a root `title` that no arm reads. objectui#7509 (PR #7622) retired the last root `title` reader across all five dashboard surfaces; `DashboardRenderer` reads `schema.label` and gates the whole header section on `header` being declared (objectui#5812). None of the six declares `header`, so they rendered no header title before that retirement and render none after — the key was already inert, and this makes the inertness total. Renaming it to `label` was rejected: it would give six shipped examples a header they have never had, which is a feature, not a cleanup. Adds a pin, because nothing else in the repo can notice the key coming back: no renderer reads it, `@object-ui/types` still declares `title?: string`, and `@objectstack/spec` — which does refuse it by name — is not this corpus's validator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
The pin's rationale turns on all three receivers accepting the key. The Zod half said "accepts it"; measured, it accepts AND preserves it (`safeParse` succeeds and `data.title` survives), because the twin does not declare `title` itself and `BaseSchema` is passthrough. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
os-sam
marked this pull request as ready for review
September 4, 2026 12:32
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7624
Deletes the root
titlekey from the sixfiltered-*entries underexamples/schema-catalog/src/schemas/plugin-dashboard/, and pins that it cannotcome back.
Disposition was ruled by PM on the card (option 2, delete). Renaming to
labelwas rejected there and is not done here: none of the six declares
header, andDashboardRenderergates its whole header section onheaderbeing declared(objectui#5812), so renaming would give six shipped examples a header they have
never had — a feature, not a cleanup.
Premise, re-verified on this branch (not inherited)
Every tracked JSON file parsed structurally, not grepped: 627 files,
9 dashboard-shaped nodes (a node with a
widgetsarray), 6 carrying aroot
title— exactly the six named on the card, all still at the file root.One refinement to the card's denominator: strict
JSON.parserefuses 83 ofthe 627 (they are JSONC
tsconfig*.jsonfiles with comments and trailingcommas). A second pass stripped comments and re-parsed all 83 — 0 additional
dashboard-shaped nodes, so the "627" figure survives, now with the whole
denominator actually parsed rather than 544 of it.
The
labelcontrol is still DARK, and is reported as such. Zero of the 627author a root
labelon a dashboard node, so the probe cannot discriminatetitlefromlabel; what it does demonstrate is that it reaches these nodes atall — it enumerated all 9 with their key sets, including the 3 without
title.That distinction is preserved, not upgraded.
No catalog regeneration is owed — verified, not assumed.
scripts/regenerate-catalog-index.pyreads curated metadata only fromsrc/catalog-meta.jsonand embeds each schema by import reference, never byinlining its content. Proven by running the repo's own tooling: the case
the checked-in index.ts matches its generatorinscripts/__tests__/catalog-index-regenerable-4633.test.ts(which shells thegenerator with
--checkagainst the real tree) passes on this branch, andsrc/index.tsis unchanged."No visible change" as a measurement, not a sentence
All 9
plugin-dashboardcatalog entries were rendered through the realSchemaRenderer, exactly as the docs gallery renders them, before and afterthe deletion:
h2elements across all 9 entriescol-span-full mb-4occurrencesThe probe is LIT, which is what makes those zeros mean something. Those 2
occurrences are not a leak: they are
widgets[0].titleinfiltered-dashboard-dynamic-options.json, whose widget title happens to be thesame string as the deleted root title, rendered as a widget card's
titleattribute plus its text node. So the probe demonstrably DOES detect title text
in the DOM when a live arm renders it — it finds the widget arm and not the
retired root arm. The two are told apart by RECEIVER, exactly as
DashboardRenderer's own comment says.Raw rendered HTML was byte-compared too: 8 of 9 entries byte-identical
before-to-after. The 9th is not attributable to this change — a control run
of the identical tree twice, with no edit between, differs on 2 of the 9,
because the chart widgets sit behind a
React.lazyboundary that resolvesnondeterministically (the AGENTS.md test-discipline phenomenon). Raw HTML bytes
are therefore a noisy probe and the stable observables above are the reading.
Why a pin for six deleted lines
Because nothing in the repo can notice the key coming back. Three receivers,
none of them red:
titleread on all five surfaces #7622) retired the roottitlearm in all five surfaces, so re-authoring it changes no pixel.
@object-ui/typesstill DECLARES it —DashboardComponentSchemacarriestitle?: string, and the Zod twin accepts and preserves it (measured:safeParsesucceeds,data.titlesurvives, since the twin does not declaretitleitself andBaseSchemais passthrough).@objectstack/specrefuses it, but is not this corpus's validator —DashboardSchema.safeParsereports the unrecognized-keys code listingtypeandtitleand naming the repair, and reports the same code listingonly
typeoncetitleis removed (that is how the reading was confirmed tobe about
titleby name, not about the document generally). But these areObjectUI SDUI component documents, not spec metadata documents: they fail that
parse either way, on
name,label, and the widgets'dataset/values. Thespec's refusal never reaches them as a gate.
The pin carries a non-vacuity case, a counter-probe proving the assertion can
still fire, and a must-not-change case asserting the live
widget.titlekeyssurvive — so a blind sweep deleting every
titlein the corpus does not satisfyit. It deliberately does not assert "zero
label":labelis the correctspelling a later card should add, so pinning its absence would turn red on the
repair.
Ablation (the pin can fail): re-authoring
"title": "Sales Overview"intofiltered-dashboard.jsonturns it RED with its intended message —2 failed | 2 passed, the two controls staying green. The mutation wasconfirmed on disk (root-title line count 0 to 1, non-empty
git diff, and themutated file still parses as JSON) and the restore leg confirmed by
git diff HEADempty plus a blob hash equal to the HEAD blob.A first ablation attempt was a MISRUN and is reported rather than discarded:
its editing one-liner ate the opening brace, so the pin failed to COLLECT
(invalid JSON) instead of failing its assertion. That red measured nothing; the
run above replaces it and now validates JSON parseability before believing any
red.
Verification
Run from the repo root, exit codes captured by redirect (never through a pipe),
all on final head
dcf8fa8d:pnpm exec vitest run examples/schema-catalog/ packages/plugin-dashboard/ scripts/__tests__/catalog-index-regenerable-4633.test.ts— 121 files, 2915 tests, all passedpnpm exec turbo run type-check --concurrency=2— 81 successful, 81 totalnode scripts/check-changeset-presence.mjs— verdict verbatim:✅ No source or published contract of a released package changed in this range, so no changeset is owed.(7 files changed, 0 published source)node scripts/check-control-bytes.mjs—✅ check-control-bytes: OK (scanned 6240 tracked text file(s); skipped 85 binary).node scripts/check-doc-component-types.mjs—✅ Every documented component type is registered.node scripts/check-governed-queue-guard.mjs --teston both changed paths —✅ NOT GOVERNEDLint is a declared narrowing, not a skip. The repo-wide
pnpm lintis CI'srun; here it was narrowed to the diff and the narrowing is measured three ways:
(1) the population comes from eslint's own config, which declares only
ts/tsxglobs — asked directly about one of the six JSON files it answers
File ignored because no matching configuration was supplied, so the JSON edits are outsideits population entirely; (2) the file count comes from
--format json: 1 filelinted, 0 errors, 0 warnings; (3) type-aware linting is not configured (no
project/projectService/parserOptionsineslint.config.js), so thisdiff cannot move the verdict of any untouched file.
Housekeeping
Clause-② — no. Re-judged from the diff, not inherited: six JSON deletions in
examples/**plus one new test file. No published surface moves, no packagesource changes, and no contract accept/reject behaviour is altered — the pin
only reads the corpus.
needs:contract-reviewis therefore not owed.Not governed — the guard's own answer on both changed paths.
Corroborates objectui#7623, does not overlap it. This branch's measurement
independently confirms that card's subject (
DashboardComponentSchema.titledeclared-but-unread).
packages/types/**is held by that dispatch and isuntouched here.
Implemented by the
domain:uiexecution seat. Session reference, as prose so itsurvives a body edit:
https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3🤖 Generated with Claude Code
https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Generated by Claude Code